﻿#pragma once

#include <setjmp.h>

#ifdef _MSC_VER
//msvc
#define THREAD_LOCAL __declspec(thread)
#else
//gcc
#define THREAD_LOCAL __thread
#endif

#ifndef MAX_CO_COUNT
#define MAX_CO_COUNT 8
#endif
#ifndef STACK_SIZE
#define STACK_SIZE 0x1000
#endif

#ifdef CORO_ISOLATION
#define CORO_STACK_ISOLATION
#define STACK_BOUND_FLAG 0x95279981
#endif

//#define DEBUG

typedef enum {
    CO_NEW,  //新协程
    CO_RUN,  //正在运行
    CO_PAUSE,//已暂停
    CO_FIN,  //已结束
} CO_STATE;

typedef struct _co_schedule co_schedule;
typedef struct _coroutine coroutine;

typedef void(*co_callback)(void* args);

struct _coroutine {
    jmp_buf         ctx;    //子协程上下文
    int             id;     //协程ID
    int             index;  //在调度器中的索引
    co_callback     func;
    void*           args;
    CO_STATE        state;
    co_schedule*    sched;
#ifdef CORO_STACK_ISOLATION
    long long       stack_bound0;//栈边界,可用于检查是否越界
    char*           stack[STACK_SIZE];
    long long       stack_bound1;//栈边界,可用于检查是否越界
#endif
};

struct _co_schedule {
    jmp_buf     ctx;    // 主协程上下文
    int         cap;
    int         currId;
    int         nextIdx;
    int         active;
    coroutine*  coros[MAX_CO_COUNT];
};

void coro_init();
void coro_create(co_callback func, void* args);
void coro_sched();
void coro_yield();
coroutine* coro_self();
